package com.godyao.mall.oauth.server.config;

import com.godyao.mall.core.model.oauth.OAuthConstant;
import com.godyao.mall.oauth.server.model.SecurityUser;
import com.godyao.mall.oauth.server.model.TokenConstant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;

import java.util.LinkedHashMap;
import java.util.Map;


/**
 * 配置令牌 JWT
 * @author godyao
 * @date 2022/4/1
 */
@Configuration
public class AccessTokenConfig {

    @Autowired
    private TokenConstant tokenConstant;

    /**
     * 配置令牌的存储策略
     * @return
     */
    @Bean
    public TokenStore tokenStore() {
        //使用JwtTokenStore生成JWT令牌
        return new JwtTokenStore(jwtAccessTokenConverter());
    }

    /**
     * TokenEnhancer的子类
     * 在JWT编码的令牌值和OAuth身份验证信息之间进行转换。
     * @return
     */
    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        //final JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
        final JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenEnhancer();
        // 设置密钥，从配置文件获取
        jwtAccessTokenConverter.setSigningKey(tokenConstant.getSignKey());
        // 设置令牌转换器 用户信息<->令牌
        final DefaultAccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter();
        accessTokenConverter.setUserTokenConverter(new JwtEnhanceUserAuthenticationConverter());
        jwtAccessTokenConverter.setAccessTokenConverter(accessTokenConverter);
        return jwtAccessTokenConverter;
    }

    /**
     * JWT令牌增强，将业务所需的额外信息放到令牌中
     */
    public static class JwtAccessTokenEnhancer extends JwtAccessTokenConverter {
        @Override
        public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
            final Object principal = authentication.getUserAuthentication().getPrincipal();
            if (principal instanceof SecurityUser) {
                final SecurityUser user = (SecurityUser) principal;
                // 将额外信息存放到一个map中
                final Map<String, Object> extendInformation = new LinkedHashMap<>();
                extendInformation.put(OAuthConstant.USER_ID, user.getUserId());
                extendInformation.put(OAuthConstant.USER_NAME, user.getUsername());
                extendInformation.put(OAuthConstant.GENDER, user.getGender());
                extendInformation.put(OAuthConstant.NICK_NAME, user.getNickname());
                extendInformation.put(OAuthConstant.AVATAR, user.getAvatar());
                extendInformation.put(OAuthConstant.MOBILE, user.getMobile());
                extendInformation.put(OAuthConstant.EMAIL, user.getEmail());
                ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(extendInformation);
            }
            return super.enhance(accessToken, authentication);
        }
    }

}
